1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.codehaus.groovy.runtime;
20
21 import groovy.lang.*;
22
23 import org.codehaus.groovy.reflection.CachedClass;
24 import org.codehaus.groovy.util.FastArray;
25 import org.codehaus.groovy.reflection.ParameterTypes;
26 import org.codehaus.groovy.reflection.ReflectionCache;
27 import org.codehaus.groovy.runtime.wrappers.Wrapper;
28
29 import java.lang.reflect.Array;
30 import java.lang.reflect.Constructor;
31 import java.lang.reflect.Modifier;
32 import java.math.BigDecimal;
33 import java.math.BigInteger;
34 import java.util.Arrays;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Set;
38 import java.util.logging.Level;
39 import java.util.logging.Logger;
40
41
42
43
44
45 public class MetaClassHelper {
46
47 public static final Object[] EMPTY_ARRAY = {};
48 public static final Class[] EMPTY_TYPE_ARRAY = {};
49 public static final Object[] ARRAY_WITH_NULL = {null};
50 protected static final Logger LOG = Logger.getLogger(MetaClassHelper.class.getName());
51 private static final int MAX_ARG_LEN = 12;
52 private static final int
53 OBJECT_SHIFT = 23, INTERFACE_SHIFT = 0,
54 PRIMITIVE_SHIFT = 21, VARGS_SHIFT = 44;
55
56
57
58
59
60
61
62 public static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
63
64 public static boolean accessibleToConstructor(final Class at, final Constructor constructor) {
65 boolean accessible = false;
66 final int modifiers = constructor.getModifiers();
67 if (Modifier.isPublic(modifiers)) {
68 accessible = true;
69 } else if (Modifier.isPrivate(modifiers)) {
70 accessible = at.getName().equals(constructor.getName());
71 } else if (Modifier.isProtected(modifiers)) {
72 Boolean isAccessible = checkCompatiblePackages(at, constructor);
73 if (isAccessible != null) {
74 accessible = isAccessible;
75 } else {
76 boolean flag = false;
77 Class clazz = at;
78 while (!flag && clazz != null) {
79 if (clazz.equals(constructor.getDeclaringClass())) {
80 flag = true;
81 break;
82 }
83 if (clazz.equals(Object.class)) {
84 break;
85 }
86 clazz = clazz.getSuperclass();
87 }
88 accessible = flag;
89 }
90 } else {
91 Boolean isAccessible = checkCompatiblePackages(at, constructor);
92 if (isAccessible != null) {
93 accessible = isAccessible;
94 }
95 }
96 return accessible;
97 }
98
99 private static Boolean checkCompatiblePackages(Class at, Constructor constructor) {
100 if (at.getPackage() == null && constructor.getDeclaringClass().getPackage() == null) {
101 return Boolean.TRUE;
102 }
103 if (at.getPackage() == null && constructor.getDeclaringClass().getPackage() != null) {
104 return Boolean.FALSE;
105 }
106 if (at.getPackage() != null && constructor.getDeclaringClass().getPackage() == null) {
107 return Boolean.FALSE;
108 }
109 if (at.getPackage().equals(constructor.getDeclaringClass().getPackage())) {
110 return Boolean.TRUE;
111 }
112 return null;
113 }
114
115 public static Object[] asWrapperArray(Object parameters, Class componentType) {
116 Object[] ret = null;
117 if (componentType == boolean.class) {
118 boolean[] array = (boolean[]) parameters;
119 ret = new Object[array.length];
120 for (int i = 0; i < array.length; i++) {
121 ret[i] = array[i];
122 }
123 } else if (componentType == char.class) {
124 char[] array = (char[]) parameters;
125 ret = new Object[array.length];
126 for (int i = 0; i < array.length; i++) {
127 ret[i] = array[i];
128 }
129 } else if (componentType == byte.class) {
130 byte[] array = (byte[]) parameters;
131 ret = new Object[array.length];
132 for (int i = 0; i < array.length; i++) {
133 ret[i] = array[i];
134 }
135 } else if (componentType == int.class) {
136 int[] array = (int[]) parameters;
137 ret = new Object[array.length];
138 for (int i = 0; i < array.length; i++) {
139 ret[i] = array[i];
140 }
141 } else if (componentType == short.class) {
142 short[] array = (short[]) parameters;
143 ret = new Object[array.length];
144 for (int i = 0; i < array.length; i++) {
145 ret[i] = array[i];
146 }
147 } else if (componentType == long.class) {
148 long[] array = (long[]) parameters;
149 ret = new Object[array.length];
150 for (int i = 0; i < array.length; i++) {
151 ret[i] = array[i];
152 }
153 } else if (componentType == double.class) {
154 double[] array = (double[]) parameters;
155 ret = new Object[array.length];
156 for (int i = 0; i < array.length; i++) {
157 ret[i] = array[i];
158 }
159 } else if (componentType == float.class) {
160 float[] array = (float[]) parameters;
161 ret = new Object[array.length];
162 for (int i = 0; i < array.length; i++) {
163 ret[i] = array[i];
164 }
165 }
166
167 return ret;
168 }
169
170
171
172
173
174
175
176 public static Object asPrimitiveArray(List list, Class parameterType) {
177 Class arrayType = parameterType.getComponentType();
178 Object objArray = Array.newInstance(arrayType, list.size());
179 for (int i = 0; i < list.size(); i++) {
180 Object obj = list.get(i);
181 if (arrayType.isPrimitive()) {
182 if (obj instanceof Integer) {
183 Array.setInt(objArray, i, (Integer) obj);
184 } else if (obj instanceof Double) {
185 Array.setDouble(objArray, i, (Double) obj);
186 } else if (obj instanceof Boolean) {
187 Array.setBoolean(objArray, i, (Boolean) obj);
188 } else if (obj instanceof Long) {
189 Array.setLong(objArray, i, (Long) obj);
190 } else if (obj instanceof Float) {
191 Array.setFloat(objArray, i, (Float) obj);
192 } else if (obj instanceof Character) {
193 Array.setChar(objArray, i, (Character) obj);
194 } else if (obj instanceof Byte) {
195 Array.setByte(objArray, i, (Byte) obj);
196 } else if (obj instanceof Short) {
197 Array.setShort(objArray, i, (Short) obj);
198 }
199 } else {
200 Array.set(objArray, i, obj);
201 }
202 }
203 return objArray;
204 }
205
206 private static final Class[] PRIMITIVES = {
207 byte.class, Byte.class, short.class, Short.class,
208 int.class, Integer.class, long.class, Long.class,
209 BigInteger.class, float.class, Float.class,
210 double.class, Double.class, BigDecimal.class,
211 Number.class, Object.class
212 };
213 private static final int[][] PRIMITIVE_DISTANCE_TABLE = {
214
215 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,},
216 {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,},
217 {14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,},
218 {14, 15, 1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,},
219 {14, 15, 12, 13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,},
220 {14, 15, 12, 13, 1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,},
221 {14, 15, 12, 13, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,},
222 {14, 15, 12, 13, 10, 11, 1, 0, 2, 3, 4, 5, 6, 7, 8, 9,},
223 {9, 10, 7, 8, 5, 6, 3, 4, 0, 14, 15, 12, 13, 11, 1, 2,},
224 {14, 15, 12, 13, 10, 11, 8, 9, 7, 0, 1, 2, 3, 4, 5, 6,},
225 {14, 15, 12, 13, 10, 11, 8, 9, 7, 1, 0, 2, 3, 4, 5, 6,},
226 {14, 15, 12, 13, 10, 11, 8, 9, 7, 5, 6, 0, 1, 2, 3, 4,},
227 {14, 15, 12, 13, 10, 11, 8, 9, 7, 5, 6, 1, 0, 2, 3, 4,},
228 {14, 15, 12, 13, 10, 11, 8, 9, 7, 5, 6, 3, 4, 0, 1, 2,},
229 {14, 15, 12, 13, 10, 11, 8, 9, 7, 5, 6, 3, 4, 2, 0, 1,},
230 {14, 15, 12, 13, 10, 11, 8, 9, 7, 5, 6, 3, 4, 2, 1, 0,},
231 };
232
233 private static int getPrimitiveIndex(Class c) {
234 for (byte i = 0; i < PRIMITIVES.length; i++) {
235 if (PRIMITIVES[i] == c) return i;
236 }
237 return -1;
238 }
239
240 private static int getPrimitiveDistance(Class from, Class to) {
241
242
243 int fromIndex = getPrimitiveIndex(from);
244 int toIndex = getPrimitiveIndex(to);
245 if (fromIndex == -1 || toIndex == -1) return -1;
246 return PRIMITIVE_DISTANCE_TABLE[toIndex][fromIndex];
247 }
248
249 private static int getMaximumInterfaceDistance(Class c, Class interfaceClass) {
250
251 if (c == null) return -1;
252
253 if (c == interfaceClass) return 0;
254 Class[] interfaces = c.getInterfaces();
255 int max = -1;
256 for (Class anInterface : interfaces) {
257 int sub = getMaximumInterfaceDistance(anInterface, interfaceClass);
258
259
260
261
262 if (sub != -1) sub++;
263
264 max = Math.max(max, sub);
265 }
266
267 int superClassMax = getMaximumInterfaceDistance(c.getSuperclass(), interfaceClass);
268 if (superClassMax != -1) superClassMax++;
269 return Math.max(max, superClassMax);
270 }
271
272 private static long calculateParameterDistance(Class argument, CachedClass parameter) {
273
274
275
276
277
278
279 if (parameter.getTheClass() == argument) return 0;
280
281 if (parameter.isInterface()) {
282 int dist = getMaximumInterfaceDistance(argument, parameter.getTheClass()) << INTERFACE_SHIFT;
283 if (dist>-1 || !(argument!=null && Closure.class.isAssignableFrom(argument))) {
284 return dist;
285 }
286 }
287
288 long objectDistance = 0;
289 if (argument != null) {
290 long pd = getPrimitiveDistance(parameter.getTheClass(), argument);
291 if (pd != -1) return pd << PRIMITIVE_SHIFT;
292
293
294 objectDistance += PRIMITIVES.length + 1;
295
296
297
298
299 if (argument.isArray() && !parameter.isArray) {
300 objectDistance+=4;
301 }
302 Class clazz = ReflectionCache.autoboxType(argument);
303 while (clazz != null) {
304 if (clazz == parameter.getTheClass()) break;
305 if (clazz == GString.class && parameter.getTheClass() == String.class) {
306 objectDistance += 2;
307 break;
308 }
309 clazz = clazz.getSuperclass();
310 objectDistance += 3;
311 }
312 } else {
313
314
315
316 Class clazz = parameter.getTheClass();
317 if (clazz.isPrimitive()) {
318 objectDistance += 2;
319 } else {
320 while (clazz != Object.class && clazz != null) {
321 clazz = clazz.getSuperclass();
322 objectDistance += 2;
323 }
324 }
325 }
326 return objectDistance << OBJECT_SHIFT;
327 }
328
329 public static long calculateParameterDistance(Class[] arguments, ParameterTypes pt) {
330 CachedClass[] parameters = pt.getParameterTypes();
331 if (parameters.length == 0) return 0;
332
333 long ret = 0;
334 int noVargsLength = parameters.length - 1;
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422 for (int i = 0; i < noVargsLength; i++) {
423 ret += calculateParameterDistance(arguments[i], parameters[i]);
424 }
425
426 if (arguments.length == parameters.length) {
427
428
429 CachedClass baseType = parameters[noVargsLength];
430 if (!parameters[noVargsLength].isAssignableFrom(arguments[noVargsLength])) {
431 baseType = ReflectionCache.getCachedClass(baseType.getTheClass().getComponentType());
432 ret += 2l << VARGS_SHIFT;
433 }
434 ret += calculateParameterDistance(arguments[noVargsLength], baseType);
435 } else if (arguments.length > parameters.length) {
436
437
438
439 ret += (2l + arguments.length - parameters.length) << VARGS_SHIFT;
440 CachedClass vargsType = ReflectionCache.getCachedClass(parameters[noVargsLength].getTheClass().getComponentType());
441 for (int i = noVargsLength; i < arguments.length; i++) {
442 ret += calculateParameterDistance(arguments[i], vargsType);
443 }
444 } else {
445
446
447
448 ret += 1l << VARGS_SHIFT;
449 }
450
451 return ret;
452 }
453
454
455
456
457
458
459
460
461
462
463 public static String capitalize(final String property) {
464 final String rest = property.substring(1);
465
466
467 if (Character.isLowerCase(property.charAt(0)) && (rest.length() > 0) && Character.isUpperCase(rest.charAt(0))) {
468 return property;
469 }
470
471 return property.substring(0, 1).toUpperCase() + rest;
472 }
473
474
475
476
477
478
479 public static Object chooseEmptyMethodParams(FastArray methods) {
480 Object vargsMethod = null;
481 final int len = methods.size();
482 final Object[] data = methods.getArray();
483 for (int i = 0; i != len; ++i) {
484 Object method = data[i];
485 final ParameterTypes pt = (ParameterTypes) method;
486 CachedClass[] paramTypes = pt.getParameterTypes();
487 int paramLength = paramTypes.length;
488 if (paramLength == 0) {
489 return method;
490 } else if (paramLength == 1 && pt.isVargsMethod(EMPTY_ARRAY)) {
491 vargsMethod = method;
492 }
493 }
494 return vargsMethod;
495 }
496
497
498
499
500
501
502
503
504
505 public static Object chooseMostGeneralMethodWith1NullParam(FastArray methods) {
506
507
508 CachedClass closestClass = null;
509 CachedClass closestVargsClass = null;
510 Object answer = null;
511 int closestDist = -1;
512 final int len = methods.size();
513 for (int i = 0; i != len; ++i) {
514 final Object[] data = methods.getArray();
515 Object method = data[i];
516 final ParameterTypes pt = (ParameterTypes) method;
517 CachedClass[] paramTypes = pt.getParameterTypes();
518 int paramLength = paramTypes.length;
519 if (paramLength == 0 || paramLength > 2) continue;
520
521 CachedClass theType = paramTypes[0];
522 if (theType.isPrimitive) continue;
523
524 if (paramLength == 2) {
525 if (!pt.isVargsMethod(ARRAY_WITH_NULL)) continue;
526 if (closestClass == null) {
527 closestVargsClass = paramTypes[1];
528 closestClass = theType;
529 answer = method;
530 } else if (closestClass.getTheClass() == theType.getTheClass()) {
531 if (closestVargsClass == null) continue;
532 CachedClass newVargsClass = paramTypes[1];
533 if (isAssignableFrom(newVargsClass.getTheClass(), closestVargsClass.getTheClass())) {
534 closestVargsClass = newVargsClass;
535 answer = method;
536 }
537 } else if (isAssignableFrom(theType.getTheClass(), closestClass.getTheClass())) {
538 closestVargsClass = paramTypes[1];
539 closestClass = theType;
540 answer = method;
541 }
542 } else {
543 if (closestClass == null || isAssignableFrom(theType.getTheClass(), closestClass.getTheClass())) {
544 closestVargsClass = null;
545 closestClass = theType;
546 answer = method;
547 closestDist = -1;
548 } else {
549
550
551 if (closestDist == -1) closestDist = closestClass.getSuperClassDistance();
552 int newDist = theType.getSuperClassDistance();
553 if (newDist < closestDist) {
554 closestDist = newDist;
555 closestVargsClass = null;
556 closestClass = theType;
557 answer = method;
558 }
559 }
560 }
561 }
562 return answer;
563 }
564
565
566
567 private static int calculateSimplifiedClassDistanceToObject(Class clazz) {
568 int objectDistance = 0;
569 while (clazz != null) {
570 clazz = clazz.getSuperclass();
571 objectDistance++;
572 }
573 return objectDistance;
574 }
575
576
577
578
579
580
581
582
583 public static boolean containsMatchingMethod(List list, MetaMethod method) {
584 for (Object aList : list) {
585 MetaMethod aMethod = (MetaMethod) aList;
586 CachedClass[] params1 = aMethod.getParameterTypes();
587 CachedClass[] params2 = method.getParameterTypes();
588 if (params1.length == params2.length) {
589 boolean matches = true;
590 for (int i = 0; i < params1.length; i++) {
591 if (params1[i] != params2[i]) {
592 matches = false;
593 break;
594 }
595 }
596 if (matches) {
597 return true;
598 }
599 }
600 }
601 return false;
602 }
603
604
605
606
607
608
609
610 public static Class[] convertToTypeArray(Object[] args) {
611 if (args == null)
612 return null;
613 int s = args.length;
614 Class[] ans = new Class[s];
615 for (int i = 0; i < s; i++) {
616 Object o = args[i];
617 ans[i] = getClassWithNullAndWrapper(o);
618 }
619 return ans;
620 }
621
622 public static Object makeCommonArray(Object[] arguments, int offset, Class fallback) {
623
624 Class baseClass = null;
625 for (int i = offset; i < arguments.length; i++) {
626 if (arguments[i] == null) continue;
627 Class argClass = arguments[i].getClass();
628 if (baseClass == null) {
629 baseClass = argClass;
630 } else {
631 for (; baseClass != Object.class; baseClass = baseClass.getSuperclass()) {
632 if (baseClass.isAssignableFrom(argClass)) break;
633 }
634 }
635 }
636 if (baseClass == null) {
637
638 baseClass = fallback;
639 }
640
641
642
643
644 if (baseClass == Object.class && fallback.isInterface()) {
645 int tmpCount = 0;
646 for (int i = offset; i < arguments.length; i++) {
647 if (arguments[i] != null) {
648 Class argClass, tmpClass;
649 Set<Class> intfs = new HashSet<Class>();
650 tmpClass = argClass = arguments[i].getClass();
651 for (; tmpClass != Object.class; tmpClass = tmpClass.getSuperclass()) {
652 intfs.addAll(Arrays.asList(tmpClass.getInterfaces()));
653 }
654 if (intfs.contains(fallback)) {
655 tmpCount++;
656 }
657 }
658 }
659
660 if (tmpCount == arguments.length - offset) {
661 baseClass = fallback;
662 }
663 }
664 Object result = makeArray(null, baseClass, arguments.length - offset);
665 System.arraycopy(arguments, offset, result, 0, arguments.length - offset);
666 return result;
667 }
668
669 public static Object makeArray(Object obj, Class secondary, int length) {
670 Class baseClass = secondary;
671 if (obj != null) {
672 baseClass = obj.getClass();
673 }
674
675
676
677 return Array.newInstance(baseClass, length);
678 }
679
680 public static GroovyRuntimeException createExceptionText(String init, MetaMethod method, Object object, Object[] args, Throwable reason, boolean setReason) {
681 return new GroovyRuntimeException(
682 init
683 + method
684 + " on: "
685 + object
686 + " with arguments: "
687 + InvokerHelper.toString(args)
688 + " reason: "
689 + reason,
690 setReason ? reason : null);
691 }
692
693 protected static String getClassName(Object object) {
694 if (object == null) return null;
695 return (object instanceof Class) ? ((Class) object).getName() : object.getClass().getName();
696 }
697
698
699
700
701
702
703
704
705
706
707 public static Closure getMethodPointer(Object object, String methodName) {
708 return new MethodClosure(object, methodName);
709 }
710
711 public static boolean isAssignableFrom(Class classToTransformTo, Class classToTransformFrom) {
712 if (classToTransformTo == classToTransformFrom
713 || classToTransformFrom == null
714 || classToTransformTo == Object.class) {
715 return true;
716 }
717
718 classToTransformTo = ReflectionCache.autoboxType(classToTransformTo);
719 classToTransformFrom = ReflectionCache.autoboxType(classToTransformFrom);
720 if (classToTransformTo == classToTransformFrom) return true;
721
722
723 if (classToTransformTo == Integer.class) {
724 if (classToTransformFrom == Short.class
725 || classToTransformFrom == Byte.class
726 || classToTransformFrom == BigInteger.class)
727 return true;
728 } else if (classToTransformTo == Double.class) {
729 if (classToTransformFrom == Integer.class
730 || classToTransformFrom == Long.class
731 || classToTransformFrom == Short.class
732 || classToTransformFrom == Byte.class
733 || classToTransformFrom == Float.class
734 || classToTransformFrom == BigDecimal.class
735 || classToTransformFrom == BigInteger.class)
736 return true;
737 } else if (classToTransformTo == BigDecimal.class) {
738 if (classToTransformFrom == Double.class
739 || classToTransformFrom == Integer.class
740 || classToTransformFrom == Long.class
741 || classToTransformFrom == Short.class
742 || classToTransformFrom == Byte.class
743 || classToTransformFrom == Float.class
744 || classToTransformFrom == BigInteger.class)
745 return true;
746 } else if (classToTransformTo == BigInteger.class) {
747 if (classToTransformFrom == Integer.class
748 || classToTransformFrom == Long.class
749 || classToTransformFrom == Short.class
750 || classToTransformFrom == Byte.class)
751 return true;
752 } else if (classToTransformTo == Long.class) {
753 if (classToTransformFrom == Integer.class
754 || classToTransformFrom == Short.class
755 || classToTransformFrom == Byte.class)
756 return true;
757 } else if (classToTransformTo == Float.class) {
758 if (classToTransformFrom == Integer.class
759 || classToTransformFrom == Long.class
760 || classToTransformFrom == Short.class
761 || classToTransformFrom == Byte.class)
762 return true;
763 } else if (classToTransformTo == Short.class) {
764 if (classToTransformFrom == Byte.class)
765 return true;
766 } else if (classToTransformTo == String.class) {
767 if (GString.class.isAssignableFrom(classToTransformFrom)) {
768 return true;
769 }
770 }
771
772 return ReflectionCache.isAssignableFrom(classToTransformTo, classToTransformFrom);
773 }
774
775 public static boolean isGenericSetMethod(MetaMethod method) {
776 return (method.getName().equals("set"))
777 && method.getParameterTypes().length == 2;
778 }
779
780 protected static boolean isSuperclass(Class clazz, Class superclass) {
781 while (clazz != null) {
782 if (clazz == superclass) return true;
783 clazz = clazz.getSuperclass();
784 }
785 return false;
786 }
787
788 public static boolean parametersAreCompatible(Class[] arguments, Class[] parameters) {
789 if (arguments.length != parameters.length) return false;
790 for (int i = 0; i < arguments.length; i++) {
791 if (!isAssignableFrom(parameters[i], arguments[i])) return false;
792 }
793 return true;
794 }
795
796 public static void logMethodCall(Object object, String methodName, Object[] arguments) {
797 String className = getClassName(object);
798 String logname = "methodCalls." + className + "." + methodName;
799 Logger objLog = Logger.getLogger(logname);
800 if (!objLog.isLoggable(Level.FINER)) return;
801 StringBuilder msg = new StringBuilder(methodName);
802 msg.append("(");
803 if (arguments != null) {
804 for (int i = 0; i < arguments.length;) {
805 msg.append(normalizedValue(arguments[i]));
806 if (++i < arguments.length) {
807 msg.append(",");
808 }
809 }
810 }
811 msg.append(")");
812 objLog.logp(Level.FINER, className, msg.toString(), "called from MetaClass.invokeMethod");
813 }
814
815 protected static String normalizedValue(Object argument) {
816 String value;
817 try {
818 value = argument.toString();
819 if (value.length() > MAX_ARG_LEN) {
820 value = value.substring(0, MAX_ARG_LEN - 2) + "..";
821 }
822 if (argument instanceof String) {
823 value = "\'" + value + "\'";
824 }
825 } catch (Exception e) {
826 value = shortName(argument);
827 }
828 return value;
829 }
830
831 protected static String shortName(Object object) {
832 if (object == null || object.getClass() == null) return "unknownClass";
833 String name = getClassName(object);
834 if (name == null) return "unknownClassName";
835 int lastDotPos = name.lastIndexOf('.');
836 if (lastDotPos < 0 || lastDotPos >= name.length() - 1) return name;
837 return name.substring(lastDotPos + 1);
838 }
839
840 public static Class[] wrap(Class[] classes) {
841 Class[] wrappedArguments = new Class[classes.length];
842 for (int i = 0; i < wrappedArguments.length; i++) {
843 Class c = classes[i];
844 if (c == null) continue;
845 if (c.isPrimitive()) {
846 if (c == Integer.TYPE) {
847 c = Integer.class;
848 } else if (c == Byte.TYPE) {
849 c = Byte.class;
850 } else if (c == Long.TYPE) {
851 c = Long.class;
852 } else if (c == Double.TYPE) {
853 c = Double.class;
854 } else if (c == Float.TYPE) {
855 c = Float.class;
856 }
857 } else if (isSuperclass(c, GString.class)) {
858 c = String.class;
859 }
860 wrappedArguments[i] = c;
861 }
862 return wrappedArguments;
863 }
864
865 public static boolean sameClasses(Class[] params, Object[] arguments, boolean weakNullCheck) {
866 if (params.length != arguments.length)
867 return false;
868
869 for (int i = params.length - 1; i >= 0; i--) {
870 Object arg = arguments[i];
871 Class compareClass = getClassWithNullAndWrapper(arg);
872 if (params[i] != compareClass) return false;
873 }
874
875 return true;
876 }
877
878 private static Class getClassWithNullAndWrapper(Object arg) {
879 if (arg == null) return null;
880 if (arg instanceof Wrapper) {
881 Wrapper w = (Wrapper) arg;
882 return w.getType();
883 }
884 return arg.getClass();
885 }
886
887 public static boolean sameClasses(Class[] params, Object[] arguments) {
888 if (params.length != arguments.length)
889 return false;
890
891 for (int i = params.length - 1; i >= 0; i--) {
892 Object arg = arguments[i];
893 if (arg == null) {
894 if (params[i] != null)
895 return false;
896 } else {
897 if (params[i] != getClassWithNullAndWrapper(arg))
898 return false;
899 }
900 }
901
902 return true;
903 }
904
905 public static boolean sameClasses(Class[] params) {
906 if (params.length != 0)
907 return false;
908
909 return true;
910 }
911
912 public static boolean sameClasses(Class[] params, Object arg1) {
913 if (params.length != 1)
914 return false;
915
916 if (params[0] != getClassWithNullAndWrapper(arg1)) return false;
917
918 return true;
919 }
920
921 public static boolean sameClasses(Class[] params, Object arg1, Object arg2) {
922 if (params.length != 2)
923 return false;
924
925 if (params[0] != getClassWithNullAndWrapper(arg1)) return false;
926 if (params[1] != getClassWithNullAndWrapper(arg2)) return false;
927
928 return true;
929 }
930
931 public static boolean sameClasses(Class[] params, Object arg1, Object arg2, Object arg3) {
932 if (params.length != 3)
933 return false;
934
935 if (params[0] != getClassWithNullAndWrapper(arg1)) return false;
936 if (params[1] != getClassWithNullAndWrapper(arg2)) return false;
937 if (params[2] != getClassWithNullAndWrapper(arg3)) return false;
938
939 return true;
940 }
941
942 public static boolean sameClasses(Class[] params, Object arg1, Object arg2, Object arg3, Object arg4) {
943 if (params.length != 4)
944 return false;
945
946 if (params[0] != getClassWithNullAndWrapper(arg1)) return false;
947 if (params[1] != getClassWithNullAndWrapper(arg2)) return false;
948 if (params[2] != getClassWithNullAndWrapper(arg3)) return false;
949 if (params[3] != getClassWithNullAndWrapper(arg4)) return false;
950
951 return true;
952 }
953
954 public static boolean sameClass(Class[] params, Object arg) {
955 return params[0] == getClassWithNullAndWrapper(arg);
956
957 }
958
959 public static Class[] castArgumentsToClassArray(Object[] argTypes) {
960 if (argTypes == null) return EMPTY_CLASS_ARRAY;
961 Class[] classes = new Class[argTypes.length];
962 for (int i = 0; i < argTypes.length; i++) {
963 Object argType = argTypes[i];
964 if (argType instanceof Class) {
965 classes[i] = (Class) argType;
966 } else if (argType == null) {
967 classes[i] = null;
968 } else {
969
970 classes[i] = argType.getClass();
971 }
972 }
973 return classes;
974 }
975
976 public static void unwrap(Object[] arguments) {
977
978
979
980
981 for (int i = 0; i != arguments.length; i++) {
982 if (arguments[i] instanceof Wrapper) {
983 arguments[i] = ((Wrapper) arguments[i]).unwrap();
984 }
985 }
986 }
987
988
989
990
991
992
993
994
995
996
997
998
999 public static void doSetMetaClass(Object self, MetaClass mc) {
1000 if (self instanceof GroovyObject) {
1001 DefaultGroovyMethods.setMetaClass((GroovyObject)self, mc);
1002 } else {
1003 DefaultGroovyMethods.setMetaClass(self, mc);
1004 }
1005 }
1006
1007
1008
1009
1010
1011
1012
1013 public static String convertPropertyName(String prop) {
1014 if (Character.isDigit(prop.charAt(0))) {
1015 return prop;
1016 }
1017 return java.beans.Introspector.decapitalize(prop);
1018 }
1019 }